from src.veiw.res.skin import S1 as Skin
import src.board.pieces as pieces
import src.board.constants as const
import src.board.fen as fen

# 棋盘 宽和高
BOARD_WIDTH = Skin.BOARD_WIDTH
BOARD_HEIGHT = Skin.BOARD_HEIGHT
# 棋子的大小
SQUARE_SIZE = Skin.SQUARE_SIZE
# 图片的子目录
IMG_DIR = Skin.IMG_DIR
# 步骤球的大小
STEP_SIZE = Skin.STEP_SIZE

# 棋子在窗口的位置，相对窗口，而非棋盘
SQUARE_LEFT = 0
# 棋子和棋盘的上边距
SQUARE_TOP = 0
# 棋子和棋盘的上（下）边距和左（右）边距
PIECE_LEFT = (BOARD_WIDTH - SQUARE_SIZE * 9) >> 1
PIECE_TOP = (BOARD_HEIGHT - SQUARE_SIZE * 10) >> 1


def sq_pos(r: int, c: int):
    """
    根据棋盘上的行和列坐标，计算出像素位置
    :param r: 棋盘上的行，从0开始
    :param c: 棋盘上的列，从0开始
    :return: x,y 该区域左上角的坐标
    """
    return SQUARE_LEFT + c * SQUARE_SIZE, SQUARE_TOP + r * SQUARE_SIZE


def piece_pos(p: pieces.Pieces):
    """
    根据棋子在棋盘上的行和列坐标，计算出像素位置
    :param p: 棋子
    :return: x,y  该棋子左上角的坐标
    """
    return sq_pos(p.r, p.c)


def set_board_pos(x: int, y: int):
    """
    设置棋盘的初始位置
    :param x:
    :param y:
    :return:
    """
    global SQUARE_LEFT
    global SQUARE_TOP
    SQUARE_LEFT = x + PIECE_LEFT
    SQUARE_TOP = y + PIECE_TOP


def get_click_pos(x, y):
    """
    根据棋盘的点击坐标，来返回点击的行和列
    :param x: x坐标
    :param y: y坐标
    :return: 点击行，列，该区域最左上解的坐标x，y
    """
    r = (y - SQUARE_TOP) // SQUARE_SIZE
    c = (x - SQUARE_LEFT) // SQUARE_SIZE
    x, y = sq_pos(r, c)
    return r, c, x, y


class Board(object):
    """
    棋盘类
    主要功能是初始化棋局，显示棋盘、棋子，响应棋盘上的点击事件
    """
    # 棋子列表
    piecesList: list[pieces.Pieces]
    # 棋盘上的90个位置盘面，每个位置可存放一个棋子
    boardList:list[list[pieces.Pieces]]

    def __init__(self):
        # img数组，对应棋盘上的90个位置区域
        self.boardList = []
        self.piecesList = []

    def from_fen(self, f):
        """
        初始化局面
        :param f:
        :return:
        """
        self.piecesList = fen.from_fen(f)
        return self.piecesList

    def from_init(self):
        """
        直接初始化默认局面
        :return:
        """
        self.piecesList.append(pieces.Rook(const.playerBlack, 0, 0))
        self.piecesList.append(pieces.Rook(const.playerBlack, 8, 0))
        self.piecesList.append(pieces.Bishop(const.playerBlack, 2, 0))
        self.piecesList.append(pieces.Bishop(const.playerBlack, 6, 0))
        self.piecesList.append(pieces.King(const.playerBlack, 4, 0))
        self.piecesList.append(pieces.Knight(const.playerBlack, 1, 0))
        self.piecesList.append(pieces.Knight(const.playerBlack, 7, 0))
        self.piecesList.append(pieces.Cannon(const.playerBlack, 1, 2))
        self.piecesList.append(pieces.Cannon(const.playerBlack, 7, 2))
        self.piecesList.append(pieces.Advisor(const.playerBlack, 3, 0))
        self.piecesList.append(pieces.Advisor(const.playerBlack, 5, 0))
        self.piecesList.append(pieces.Pawn(const.playerBlack, 0, 3))
        self.piecesList.append(pieces.Pawn(const.playerBlack, 2, 3))
        self.piecesList.append(pieces.Pawn(const.playerBlack, 4, 3))
        self.piecesList.append(pieces.Pawn(const.playerBlack, 6, 3))
        self.piecesList.append(pieces.Pawn(const.playerBlack, 8, 3))

        self.piecesList.append(pieces.Rook(const.playerRed, 0, 9))
        self.piecesList.append(pieces.Rook(const.playerRed, 8, 9))
        self.piecesList.append(pieces.Bishop(const.playerRed, 2, 9))
        self.piecesList.append(pieces.Bishop(const.playerRed, 6, 9))
        self.piecesList.append(pieces.King(const.playerRed, 4, 9))
        self.piecesList.append(pieces.Knight(const.playerRed, 1, 9))
        self.piecesList.append(pieces.Knight(const.playerRed, 7, 9))
        self.piecesList.append(pieces.Cannon(const.playerRed, 1, 7))
        self.piecesList.append(pieces.Cannon(const.playerRed, 7, 7))
        self.piecesList.append(pieces.Advisor(const.playerRed, 3, 9))
        self.piecesList.append(pieces.Advisor(const.playerRed, 5, 9))
        self.piecesList.append(pieces.Pawn(const.playerRed, 0, 6))
        self.piecesList.append(pieces.Pawn(const.playerRed, 2, 6))
        self.piecesList.append(pieces.Pawn(const.playerRed, 4, 6))
        self.piecesList.append(pieces.Pawn(const.playerRed, 6, 6))
        self.piecesList.append(pieces.Pawn(const.playerRed, 8, 6))

        return self.piecesList

    def move(self, sid: int, c: int, r: int, tid: int = None):
        """
        走棋
        :param sid:  源棋子在数组中的ID
        :param c: 目标的棋盘列
        :param r: 目标的棋盘行
        :param tid: 目标位置的棋子ID，如果目标位置没棋子，侧值为None
        :return:  成功 true,其它失败
        """

        # 获取源棋子，根据步骤，进行判断是否可以走
        s_pieces = self.piecesList[sid]
        if s_pieces.canmove(pieces.list_piecesto_arr(self.piecesList), c, r):
            # 如果可以走，则更新原棋子的坐标到新位置
            s_pieces.set_pos_board(c, r)

            # 如果目标位置有棋子，则删除目标棋子，以表示吃掉对方
            if tid is not None:
                t_pieces = self.piecesList[tid]
                t_pieces.set_pos_board(-1, -1)

            return True
        else:
            return False

    def get_piece_rc(self, ind: int):
        """
        根据棋子的ID，获取棋子在棋盘上的列和行
        :param ind: 棋子ID
        :return: c,r 棋子所在的列和行
        """
        piece = self.piecesList[ind]
        if piece is not None:
            return piece.c, piece.r
        else:
            return None, None

    def get_next_steps_tip(self, piece_id: int):
        """
        指定棋子，算出可走的棋步数组
        :param piece_id: 棋子Id
        :return: 可走的步子列表(r,c)
        """
        result = []
        piece = self.piecesList[piece_id]
        if piece is not None:
            result = piece.get_next_steps_tip(pieces.list_piecesto_arr(self.piecesList))
        return result
